package com.campus.service.impl;

import com.campus.domain.dto.*;
import com.campus.domain.entity.*;
import com.campus.domain.vo.*;
import com.campus.mapper.*;
import com.campus.service.ILostItemService;
import com.campus.utils.AliyunOssOperator;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 失物招领Service实现类
 */
@Service
public class LostItemServiceImpl implements ILostItemService {
    
    @Resource
    private LostItemMapper lostItemMapper;
    
    @Resource
    private LostItemImageMapper lostItemImageMapper;
    
    @Resource
    private LostItemLikeMapper lostItemLikeMapper;
    
    @Resource
    private LostItemClaimMapper lostItemClaimMapper;
    
    @Resource
    private LostItemCommentMapper lostItemCommentMapper;
    
    @Resource
    private CommentLikeMapper commentLikeMapper;
    
    @Resource
    private CommentReplyMapper commentReplyMapper;
    
    @Resource
    private ReplyLikeMapper replyLikeMapper;
    
    @Resource
    private UserMapper userMapper;
    
    @Resource
    private AliyunOssOperator aliyunOssOperator;
    
    /**
     * 获取当前登录用户ID
     */
    private Long getCurrentUserId() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof UserDTO) {
                UserDTO userDTO = (UserDTO) authentication.getPrincipal();
                return userDTO.getId();
            }
        } catch (Exception e) {
            // 未登录或获取用户信息失败
        }
        return null;
    }
    
    @Override
    public UploadImageVO uploadImage(MultipartFile file) throws Exception {
        // 上传到阿里云OSS
        String url = aliyunOssOperator.upload(file.getBytes(), Objects.requireNonNull(file.getOriginalFilename()));
        return new UploadImageVO(url);
    }
    
    @Override
    @Transactional
    public Long publishLostItem(String title, String description, String location,
                                String foundTime, String category, String[] imageUrls) {
        // 获取当前用户ID
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }

        // 插入失物信息
        LostItem lostItem = new LostItem();
        lostItem.setUserId(userId);
        lostItem.setTitle(title);
        lostItem.setDescription(description);
        lostItem.setLocation(location);
        lostItem.setFoundTime(LocalDateTime.parse(foundTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        lostItem.setCategory(category);
        lostItemMapper.insert(lostItem);
        
        // 插入图片
        if (imageUrls != null && imageUrls.length > 0) {
            List<LostItemImage> images = new ArrayList<>();
            for (int i = 0; i < imageUrls.length; i++) {
                LostItemImage image = new LostItemImage();
                image.setItemId(lostItem.getId());
                image.setImageUrl(imageUrls[i]);
                image.setSortOrder(i);
                images.add(image);
            }
            lostItemImageMapper.batchInsert(images);
        }
        
        return lostItem.getId();
    }
    
    @Override
    public PageResultVO<LostItemVO> getLostItemList(LostItemQueryDTO queryDTO) {
        // 获取当前用户ID
        final Long currentUserId = getCurrentUserId();
        
        // 计算分页参数
        int offset = (queryDTO.getPage() - 1) * queryDTO.getPageSize();
        queryDTO.setPage(offset);
        
        // 查询列表
        List<LostItem> lostItems = lostItemMapper.selectList(queryDTO);
        Long total = lostItemMapper.selectCount(queryDTO);
        
        // 转换为VO
        List<LostItemVO> voList = lostItems.stream().map(item -> {
            LostItemVO vo = new LostItemVO();
            BeanUtils.copyProperties(item, vo);
            
            // 获取图片
            List<LostItemImage> images = lostItemImageMapper.selectByItemId(item.getId());
            vo.setImages(images.stream().map(LostItemImage::getImageUrl).collect(Collectors.toList()));
            
            // 获取用户信息
            User user = userMapper.findById(item.getUserId());
            if (user != null) {
                vo.setUserName(user.getUserName());
                vo.setUserAvatar(user.getAvatar());
            }
            
            // 判断当前用户是否点赞
            if (currentUserId != null) {
                vo.setIsLiked(lostItemLikeMapper.exists(item.getId(), currentUserId) > 0);
            }
            
            return vo;
        }).collect(Collectors.toList());
        
        PageResultVO<LostItemVO> result = new PageResultVO<>();
        result.setRecords(voList);
        result.setTotal(total);
        result.setPage((offset / queryDTO.getPageSize()) + 1);
        result.setPageSize(queryDTO.getPageSize());
        
        return result;
    }
    
    @Override
    public LostItemVO getLostItemDetail(Long id) {
        // 获取当前用户ID
        Long currentUserId = getCurrentUserId();
        
        // 增加浏览数
        lostItemMapper.incrementViewCount(id);
        
        // 查询失物
        LostItem lostItem = lostItemMapper.selectById(id);
        if (lostItem == null) {
            throw new RuntimeException("失物不存在");
        }
        
        // 转换为VO
        LostItemVO vo = new LostItemVO();
        BeanUtils.copyProperties(lostItem, vo);
        
        // 获取图片
        List<LostItemImage> images = lostItemImageMapper.selectByItemId(id);
        vo.setImages(images.stream().map(LostItemImage::getImageUrl).collect(Collectors.toList()));
        
        // 获取用户信息
        User user = userMapper.findById(lostItem.getUserId());
        if (user != null) {
            vo.setUserName(user.getUserName());
            vo.setUserAvatar(user.getAvatar());
        }
        
        // 判断当前用户是否点赞
        if (currentUserId != null) {
            vo.setIsLiked(lostItemLikeMapper.exists(id, currentUserId) > 0);
        }
        
        return vo;
    }
    
    @Override
    @Transactional
    public void updateLostItem(Long id, String title, String description,
                              String location, String foundTime, String category, String[] imageUrls) {
        // 更新失物信息
        LostItem lostItem = new LostItem();
        lostItem.setId(id);
        lostItem.setTitle(title);
        lostItem.setDescription(description);
        lostItem.setLocation(location);
        lostItem.setFoundTime(LocalDateTime.parse(foundTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        lostItem.setCategory(category);
        lostItemMapper.update(lostItem);
        
        // 删除旧图片
        lostItemImageMapper.deleteByItemId(id);
        
        // 插入新图片
        if (imageUrls != null && imageUrls.length > 0) {
            List<LostItemImage> images = new ArrayList<>();
            for (int i = 0; i < imageUrls.length; i++) {
                LostItemImage image = new LostItemImage();
                image.setItemId(id);
                image.setImageUrl(imageUrls[i]);
                image.setSortOrder(i);
                images.add(image);
            }
            lostItemImageMapper.batchInsert(images);
        }
    }
    
    @Override
    public void deleteLostItem(Long id) {
        lostItemMapper.deleteById(id);
    }
    
    @Override
    @Transactional
    public void likeItem(Long itemId) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 检查是否已点赞
        if (lostItemLikeMapper.exists(itemId, userId) > 0) {
            throw new RuntimeException("已经点赞过了");
        }
        
        // 插入点赞记录
        LostItemLike like = new LostItemLike();
        like.setItemId(itemId);
        like.setUserId(userId);
        lostItemLikeMapper.insert(like);
        
        // 增加点赞数
        lostItemMapper.incrementLikeCount(itemId);
    }
    
    @Override
    @Transactional
    public void unlikeItem(Long itemId) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 删除点赞记录
        lostItemLikeMapper.delete(itemId, userId);
        
        // 减少点赞数
        lostItemMapper.decrementLikeCount(itemId);
    }
    
    @Override
    @Transactional
    public void claimItem(ClaimDTO claimDTO) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 检查失物状态
        LostItem item = lostItemMapper.selectById(claimDTO.getItemId());
        if (item.getStatus() != 0) {
            throw new RuntimeException("该失物已被申领或已归还");
        }
        
        // 检查是否已申领
        if (lostItemClaimMapper.exists(claimDTO.getItemId(), userId) > 0) {
            throw new RuntimeException("您已经申领过该失物");
        }
        
        // 创建申领记录
        LostItemClaim claim = new LostItemClaim();
        claim.setItemId(claimDTO.getItemId());
        claim.setUserId(userId);
        claim.setReason(claimDTO.getReason());
        claim.setContactInfo(claimDTO.getContactInfo());
        claim.setStatus(0); // 待审核
        lostItemClaimMapper.insert(claim);
        
        // 更新失物状态为已申领
        lostItemMapper.updateStatus(claimDTO.getItemId(), 1);
    }
    
    @Override
    @Transactional
    public Long addComment(CommentDTO commentDTO) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        LostItemComment comment = new LostItemComment();
        comment.setItemId(commentDTO.getItemId());
        comment.setUserId(userId);
        comment.setContent(commentDTO.getContent());
        lostItemCommentMapper.insert(comment);
        
        // 增加失物评论数
        lostItemMapper.incrementCommentCount(commentDTO.getItemId());
        
        return comment.getId();
    }
    
    @Override
    public PageResultVO<CommentVO> getCommentList(Long itemId, Integer page, Integer pageSize) {
        Long currentUserId = getCurrentUserId();
        
        // 计算分页参数
        int offset = (page - 1) * pageSize;
        
        // 查询评论列表
        List<LostItemComment> comments = lostItemCommentMapper.selectByItemId(itemId, offset, pageSize);
        Long total = lostItemCommentMapper.countByItemId(itemId);
        
        // 转换为VO
        List<CommentVO> voList = comments.stream().map(comment -> {
            CommentVO vo = new CommentVO();
            BeanUtils.copyProperties(comment, vo);
            
            // 获取用户信息
            User user = userMapper.findById(comment.getUserId());
            if (user != null) {
                vo.setUserName(user.getUserName());
                vo.setUserAvatar(user.getAvatar());
            }
            
            // 判断当前用户是否点赞
            if (currentUserId != null) {
                vo.setIsLiked(commentLikeMapper.exists(comment.getId(), currentUserId) > 0);
            }
            
            // 获取回复列表
            List<CommentReply> replies = commentReplyMapper.selectByCommentId(comment.getId());
            List<ReplyVO> replyVOList = replies.stream().map(reply -> {
                ReplyVO replyVO = new ReplyVO();
                BeanUtils.copyProperties(reply, replyVO);
                
                // 获取回复者信息
                User replyUser = userMapper.findById(reply.getUserId());
                if (replyUser != null) {
                    replyVO.setUserName(replyUser.getUserName());
                    replyVO.setUserAvatar(replyUser.getAvatar());
                }
                
                // 获取被回复者信息
                if (reply.getReplyToUserId() != null) {
                    User replyToUser = userMapper.findById(reply.getReplyToUserId());
                    if (replyToUser != null) {
                        replyVO.setReplyToUserName(replyToUser.getUserName());
                    }
                }
                
                // 判断当前用户是否点赞回复
                if (currentUserId != null) {
                    replyVO.setIsLiked(replyLikeMapper.exists(reply.getId(), currentUserId) > 0);
                }
                
                return replyVO;
            }).collect(Collectors.toList());
            
            vo.setReplies(replyVOList);
            
            return vo;
        }).collect(Collectors.toList());
        
        PageResultVO<CommentVO> result = new PageResultVO<>();
        result.setRecords(voList);
        result.setTotal(total);
        
        return result;
    }
    
    @Override
    public void deleteComment(Long commentId) {
        lostItemCommentMapper.deleteById(commentId);
    }
    
    @Override
    @Transactional
    public void likeComment(Long commentId) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 检查是否已点赞
        if (commentLikeMapper.exists(commentId, userId) > 0) {
            throw new RuntimeException("已经点赞过了");
        }
        
        // 插入点赞记录
        CommentLike like = new CommentLike();
        like.setCommentId(commentId);
        like.setUserId(userId);
        commentLikeMapper.insert(like);
        
        // 增加点赞数
        lostItemCommentMapper.incrementLikeCount(commentId);
    }
    
    @Override
    @Transactional
    public void unlikeComment(Long commentId) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 删除点赞记录
        commentLikeMapper.delete(commentId, userId);
        
        // 减少点赞数
        lostItemCommentMapper.decrementLikeCount(commentId);
    }
    
    @Override
    @Transactional
    public Long addReply(ReplyDTO replyDTO) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        CommentReply reply = new CommentReply();
        reply.setCommentId(replyDTO.getCommentId());
        reply.setUserId(userId);
        reply.setReplyToUserId(replyDTO.getReplyToUserId());
        reply.setContent(replyDTO.getContent());
        commentReplyMapper.insert(reply);
        
        // 增加评论回复数
        lostItemCommentMapper.incrementReplyCount(replyDTO.getCommentId());
        
        return reply.getId();
    }
    
    @Override
    public void deleteReply(Long replyId) {
        commentReplyMapper.deleteById(replyId);
    }
    
    @Override
    @Transactional
    public void likeReply(Long replyId) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 检查是否已点赞
        if (replyLikeMapper.exists(replyId, userId) > 0) {
            throw new RuntimeException("已经点赞过了");
        }
        
        // 插入点赞记录
        ReplyLike like = new ReplyLike();
        like.setReplyId(replyId);
        like.setUserId(userId);
        replyLikeMapper.insert(like);
        
        // 增加点赞数
        commentReplyMapper.incrementLikeCount(replyId);
    }
    
    @Override
    @Transactional
    public void unlikeReply(Long replyId) {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 删除点赞记录
        replyLikeMapper.delete(replyId, userId);
        
        // 减少点赞数
        commentReplyMapper.decrementLikeCount(replyId);
    }
    
    @Override
    public PageResultVO<ClaimAuditVO> getPendingClaims(Integer page, Integer pageSize) {
        // 查询待审核申领列表
        List<LostItemClaim> claims = lostItemClaimMapper.selectPendingClaims();
        
        // 转换为VO
        List<ClaimAuditVO> voList = claims.stream().map(claim -> {
            ClaimAuditVO vo = new ClaimAuditVO();
            BeanUtils.copyProperties(claim, vo);
            
            // 查询失物信息
            LostItem item = lostItemMapper.selectById(claim.getItemId());
            if (item != null) {
                vo.setItemTitle(item.getTitle());
                vo.setItemCategory(item.getCategory());
                vo.setItemLocation(item.getLocation());
            }
            
            // 查询用户信息
            User user = userMapper.findById(claim.getUserId());
            if (user != null) {
                vo.setUsername(user.getUserName());
            }
            
            return vo;
        }).collect(Collectors.toList());
        
        // 分页处理
        int total = voList.size();
        int start = (page - 1) * pageSize;
        int end = Math.min(start + pageSize, total);
        
        List<ClaimAuditVO> pagedList = start < total ? voList.subList(start, end) : new ArrayList<>();
        
        return new PageResultVO<>(pagedList, (long) total, page, pageSize);
    }
    
    @Override
    @Transactional
    public void auditClaim(AuditClaimDTO auditDTO) {
        // 查询申领记录
        LostItemClaim claim = lostItemClaimMapper.selectById(auditDTO.getClaimId());
        if (claim == null) {
            throw new RuntimeException("申领记录不存在");
        }
        
        // 更新审核状态
        lostItemClaimMapper.updateAuditStatus(
            auditDTO.getClaimId(),
            auditDTO.getStatus(),
            auditDTO.getAuditReason()
        );
        
        // 根据审核结果更新失物状态
        if (auditDTO.getStatus() == 1) {
            // 审核通过，更新失物状态为已归还
            lostItemMapper.updateStatus(claim.getItemId(), 2);
        } else if (auditDTO.getStatus() == 2) {
            // 审核驳回，将失物状态改回待认领
            lostItemMapper.updateStatus(claim.getItemId(), 0);
        }
    }
}

